package com.supermarket.manage.provider.product.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.supermarket.manage.common.constant.ProductConstant;
import com.supermarket.manage.common.constant.RedisKeyConstant;
import com.supermarket.manage.common.dto.prod.response.CategoryDto;
import com.supermarket.manage.common.pojo.ProductCategory;
import com.supermarket.manage.provider.api.product.ProductCategoryService;
import com.supermarket.manage.provider.product.mapper.ProductCategoryMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author Faxon
 * @version 1.0
 * @date 2020-03-08 19:17
 **/
@Service(version = "1.0.0")
public class ProductCategoryServiceImpl implements ProductCategoryService {

    @Resource
    private ProductCategoryMapper productCategoryMapper;

    @Resource
    private RedisTemplate<String, String> redisTemplate;


    @Override
    public Integer getCountByCname(String cname, String buyerId) {
        QueryWrapper<ProductCategory> wrapper = new QueryWrapper<>();
        wrapper.eq("buyer_id", buyerId).eq("cname", cname);
        return productCategoryMapper.selectCount(wrapper);
    }

    @Override
    public Boolean addCategory(ProductCategory category) {
        //添加到数据库
        Date date = new Date();
        category.setCreated(date);
        category.setUpdated(date);
        int i = productCategoryMapper.insert(category);
        if (i == 1) {
            //删除redis
            deleteCategoryFromRedis(category.getBuyerId());
        }
        return i == 1;
    }

    @Override
    public Integer getChildCountByCid(String cid) {
        QueryWrapper<ProductCategory> wrapper = new QueryWrapper<>();
        wrapper.eq("fid", cid);
        return productCategoryMapper.selectCount(wrapper);
    }

    @Override
    public Boolean deleteByCid(String cid, String buyerId) {
        int i = productCategoryMapper.deleteById(cid);
        if (i == 1) {
            //删除redis
            deleteCategoryFromRedis(buyerId);
        }
        return i == 1;
    }

    @Override
    public ProductCategory getCategoryByCid(String cid) {
        return productCategoryMapper.selectById(cid);
    }

    @Override
    public Boolean updateCnameByCid(ProductCategory newCategory) {
        //更新数据库
        Date updated = new Date();
        newCategory.setUpdated(updated);
        int i = productCategoryMapper.updateById(newCategory);
        if (i == 1) {
            //删除redis
            deleteCategoryFromRedis(newCategory.getBuyerId());
        }
        return i == 1;
    }

    @Override
    public Set<CategoryDto> getCategoryList(String buyerId) {
        //从redis中查询
        Set<CategoryDto> categoryDtos = getCategoryDtosFromRedis(buyerId);
        if (categoryDtos == null || categoryDtos.size() == 0) {
            //没有则查询数据库，并保存到redis
            categoryDtos = productCategoryMapper.getAllCategoryByBuyerId(buyerId);
            saveCategoryToRedis(categoryDtos, buyerId);
        }
        return categoryDtos;
    }

    @Override
    public String getCatName(String redisKey, String cid, String buyerId) {
        if (!redisTemplate.hasKey(redisKey)) {
            Set<CategoryDto> categoryDtos = productCategoryMapper.getAllCategoryByBuyerId(buyerId);
            saveCategoryToRedis(categoryDtos, buyerId);
        }
        String json = redisTemplate.<String, String>opsForHash().get(redisKey, cid);
        if (StringUtils.isNotBlank(json)) {
            CategoryDto categoryDto = JSON.parseObject(json, CategoryDto.class);
            return categoryDto.getCname();
        } else {
            ProductCategory category = getCategoryByCid(cid);
            return category.getCname();
        }
    }

    private Set<CategoryDto> getCategoryDtosFromRedis(String buyerId) {
        Set<CategoryDto> categoryDtos = new HashSet<>();
        //从redis获取各级分类
        List<String> first = redisTemplate.<String, String>opsForHash().values(RedisKeyConstant.FIRST_CAT + buyerId);
        List<String> second = redisTemplate.<String, String>opsForHash().values(RedisKeyConstant.SECOND_CAT + buyerId);
        List<String> third = redisTemplate.<String, String>opsForHash().values(RedisKeyConstant.THIRD_CAT + buyerId);
        if (first != null && first.size() > 0) {
            //遍历一级分类
            first.forEach(f -> {
                CategoryDto c1 = JSON.parseObject(f, CategoryDto.class);
                //遍历二级分类
                if (second != null && second.size() > 0) {
                    second.forEach(s -> {
                        CategoryDto c2 = JSON.parseObject(s, CategoryDto.class);
                        if (c2.getFid().equals(c1.getCid())) {
                            //设置一级分类的子类
                            c1.getChildCategory().add(c2);
                        }
                        if (third != null && third.size() > 0) {
                            third.forEach(t -> {
                                CategoryDto c3 = JSON.parseObject(t, CategoryDto.class);
                                if (c3.getFid().equals(c2.getCid())) {
                                    //设置二级分类的子类
                                    c2.getChildCategory().add(c3);
                                }
                            });
                        }
                    });
                }
                categoryDtos.add(c1);
            });
        }
        return categoryDtos;
    }

    private void saveCategoryToRedis(Set<CategoryDto> categoryDtos, String buyerId) {
        Map<String, String> first = new HashMap<>(16);
        Map<String, String> second = new HashMap<>(16);
        Map<String, String> third = new HashMap<>(16);
        categoryDtos.forEach(c -> {
            first.put(c.getCid(), JSON.toJSONString(c));
            Set<CategoryDto> secondCategory = c.getChildCategory();
            secondCategory.forEach(c2 -> {
                second.put(c2.getCid(), JSON.toJSONString(c2));
                Set<CategoryDto> thirdCategory = c2.getChildCategory();
                thirdCategory.forEach(c3 -> {
                    third.put(c3.getCid(), JSON.toJSONString(c3));
                });
            });
        });
        if (first != null && first.size() > 0) {
            redisTemplate.opsForHash().putAll(RedisKeyConstant.FIRST_CAT + buyerId, first);
        }
        if (second != null && second.size() > 0) {
            redisTemplate.opsForHash().putAll(RedisKeyConstant.SECOND_CAT + buyerId, second);
        }
        if (third != null && third.size() > 0) {
            redisTemplate.opsForHash().putAll(RedisKeyConstant.THIRD_CAT + buyerId, third);
        }

    }

    private void deleteCategoryFromRedis(String buyerId) {
        redisTemplate.delete(RedisKeyConstant.FIRST_CAT + buyerId);
        redisTemplate.delete(RedisKeyConstant.SECOND_CAT + buyerId);
        redisTemplate.delete(RedisKeyConstant.THIRD_CAT + buyerId);
    }
}
